home *** CD-ROM | disk | FTP | other *** search
- NAME ccssen
- ; File CCSSEN.ASM
-
- ;CHINESE
- ifdef MSDOS
- include msssen.dat
- else
- include ccssen.dat
- endif
-
- code segment public 'code'
- extrn serini:near, serrst:near, comnd:near, init:near
- extrn spack:near, rpack:near, gtnfil:near, gtchr:near
- extrn getfil:near, clrfln:near, nppos:near, rprpos:near, prtasz:near
- extrn erpos:near, rtpos:near, cxmsg:near, stpos:near, decout:near
- extrn encode:near, nulref:near, decode:near, nulr:near, lnout:near
- extrn errpack:near, updrtr:near, clrmod:near, prompt:near
- extrn prtfn:near, strcpy:near, strlen:near, strcat:near, pktsize:near
- extrn pcwait:near, ihosts:near, begtim:near, endtim:near
-
- assume cs:code, ds:datas
-
- ; This routine sets up the data for init packet (either the
- ; Send_init or ACK packet)
- ; trans.rxxx are items we are prepared to receive
- ; Lines marked ;M energize the second CAPAS byte. Leave them as comments for
- ; because earlier versions of MS Kermit (and C Kermit) are confused by it
- ; (fail to decode bit saying second CAPAS byte follows and thus loose sync).
- RPAR PROC NEAR
- mov ah,trans.rpsiz ; Get the receive packet size
- add ah,' ' ; Add a space to make it printable
- mov [bx],ah ; Put it in the packet
- mov ah,trans.rtime ; Get the receive packet time out
- add ah,' ' ; Add a space
- mov 1[bx],ah ; Put it in the packet
- mov ah,trans.rpad ; Get the number of padding chars
- add ah,' '
- mov 2[bx],ah ; Put it in the packet
- mov ah,trans.rpadch ; Get the padding char
- add ah,40h ; Uncontrol it
- and ah,7FH
- mov 3[bx],ah ; Put it in the packet
- mov ah,trans.reol ; Get the EOL char
- add ah,' '
- mov 4[bx],ah ; Put it in the packet
- mov ah,trans.rquote ; Get the quote char
- mov 5[bx],ah ; Put it in the packet
- mov ah,trans.ebquot ; Get 8-bit quote char
- mov 6[bx],ah ; Add it to the packet
- mov ah,trans.chklen ; Length of checksum
- add ah,'0' ; Make into a real digit
- mov 7[bx],ah
- mov ah,rptq ; Repeat quote char
- cmp ah,0 ; Null means no
- jne rpar0
- mov ah,' ' ; Send a blank instead
- rpar0: mov 8[bx],ah
- ; begin long packet changes
- mov ah,2 ; CAPAS, bit1 = can do long packets
- cmp flags.attflg,0 ; allowing attributes packets?
- je rpar1 ; e = no
- or ah,8 ; bit #3, can do file attributes
- rpar1:
- ;M or ah,1 ; say second CAPAS byte follows
- add ah,20h ; apply tochar() to byte
- mov 9[bx],ah ; add to packet
- ; additional CAPAS go in here
- mov byte ptr 10[bx],20h+20h ; Allow M (message) pkts, (#6, bit5)
- mov ah,20h ; WINDO field, null applied through tochar()
- ;M mov 11[bx],ah ; put into packet
- mov 10[bx],ah ; put into packet
-
- push ax ; save some regs
- push dx
- mov ax,trans.rlongp ; long packet length which we can receive
- xor dx,dx ; clear extended part for division
- div ninefive ; divide by 95. quo = ax, rem = dx
- add al,20h ; apply tochar() to quotient
- ;M mov 12[bx],al ; add to packet
- mov 11[bx],al ; add to packet
- add dl,20h ; apply tochar() to remainder
- ;M mov 13[bx],dl ; add to packet
- mov 12[bx],dl ; add to packet
- pop dx ; restore regs
- pop ax
- ;M mov ah,14 ; 14 bytes of data
- mov ah,13 ; 13 bytes of data
- ret
- RPAR ENDP
-
- ; This routine reads in all the send init packet information
- ; Enter with BX/ packet address, AX/ packet length
- ; This could probably be done much more legibly if it were table
- ; driven, but I'm afraid to touch it..
- ;
- ; dtrans.xxx are the default parameters if the other side says nothing
- ; trans.sxxx are the active negotiated parameters we will use for sending.
- SPAR PROC NEAR
- mov temp4,ax ; Save the number of arguments
- mov ah,al ; number of args is now in ah
- push si
- mov si,bx
- cld
- cmp ah,0 ; any data?
- jg spara ; g = yes, want more than bare minimum
- mov al,dspsiz ; nothing supplied by host use default
- jmp short sparc
- spara: lodsb ; get the max packet size
- dec ah ; ah = bytes remaining to be examined
- sub al,' ' ; subtract a space
- cmp al,spmin ; below the minimum?
- jge sparb ; ge = no
- mov al,spmin
- jmp short sparc
- sparb: cmp al,spmax ; or above the maximum?
- jle sparc ; le = no
- mov al,spmax
- sparc: mov trans.spsiz,al ; save it
- mov al,dtrans.stime ; pick up default stime
- cmp ah,0 ; more data?
- jle spar02 ; le = no, use default
- lodsb ; get the timeout value
- dec ah
- sub al,' ' ; subtract a space
- cmp dtrans.stime,dstime ; Is current value the default?
- je spar0 ; e = yes, else user value overrides
- mov al,dtrans.stime ; pick up user selected stime
- spar0: cmp al,0
- jg spar01 ; must be non-negative
- mov al,0 ; negative, so use zero
- spar01: cmp al,trans.rtime ; same as other side's timeout
- jne spar02 ; ne = no
- add al,1 ; yes, but make it a little different
- spar02: mov trans.stime,al ; save it
- mov al,dtrans.spad ; get default send padding
- cmp ah,0 ; more data?
- jle spar11 ; le = no, use default
- spar1: lodsb ; get the number of padding chars
- dec ah
- sub al,' '
- cmp al,0
- jge spar11 ; must be non-negative
- mov al,0
- spar11: mov trans.spad,al
- mov al,dtrans.spadch ; pick up default send pad character
- cmp ah,0 ; more data?
- jle spar21 ; le = no, use default
- spar2: lodsb ; get the padding char
- dec ah
- add al,40h ; remove ascii bias
- and al,7FH
- cmp al,del ; Delete?
- je spar21 ; e = yes, then it's OK
- cmp al,31 ; control char?
- jle spar21 ; le = yes, then OK
- mov al,0 ; no, use null
- spar21: mov trans.spadch,al
- mov al,dtrans.seol ; get default send eol char
- cmp ah,0 ; more data?
- jle spar31 ; le = no, use default
- spar3: lodsb ; get the EOL char
- dec ah
- sub al,' '
- cmp al,31 ; control char?
- jle spar31 ; le = yes, then use it
- mov al,cr ; else use the default
- spar31: mov trans.seol,al
- mov al,dtrans.squote ; send quote
- cmp ah,0 ; more data?
- jle spar41 ; le = no, use default
- spar4: lodsb ; get the quote char
- dec ah
- cmp al,' ' ; less than a space?
- jge spar40 ; ge = no
- mov al,dsquot ; yes, use default
- jmp spar41
- spar40: cmp al,7eh ; must also be less than a tilde
- jbe spar41 ; be = is ok
- mov al,dsquot ; else use default
- spar41: mov trans.squote,al
- cmp ah,0 ; more data?
- jg spar5 ; g = yes
- mov al,dtrans.ebquot ; use default
- mov trans.ebquot,al
- jmp short spar51
- spar5: lodsb ; get other side's 8-bit quote request
- dec ah
- call doquo ; and set quote char
- spar51: cmp ah,0 ; more data?
- jg spar6 ; g = yes
- mov trans.chklen,1 ; use default
- jmp short spar61
- spar6: mov al,inichk
- mov trans.chklen,al ;checksum length we really want to use
- lodsb ; get other side's checksum length
- dec ah
- call dochk ; determine what size to use
- spar61: cmp ah,0 ; more data?
- jg spar7 ; g = yes
- mov rptq,0
- jmp short spar71
- spar7: lodsb ; get other side's repeat count prefix
- dec ah
- mov ch,drpt ; default repeat count prefix
- mov rptq,0 ; clear active repeat count prefix
- call dorpt ; negotiate new prefix
- spar71: mov al,0 ; get default operating Capabilities
- cmp ah,0 ; more data?
- jle spar81 ; le = no, use default
- lodsb ; get capas bitmap from other side
- dec ah
- and al,not (1) ; remove least significant bit
- sub al,20h ; apply unchar()
- spar81: mov trans.capas,al ; store result in active byte
- spar82: cmp ah,0 ; more data?
- jle spar85 ; le = no
- test byte ptr [si-1],1 ; is CAPAS byte continued to next?
- jz spar85 ; z = no
- lodsb ; get 2nd CAPAS bitmap from other side
- dec ah
- and al,not (1) ; remove least significant bit
- sub al,20h ; apply unchar(). Store nothing
- jmp short spar82 ; seek more CAPAS bytes
- spar85: mov al,0 ; setup default window size
- cmp ah,0 ; more data?
- jle spar9 ; le = no, use default
- lodsb ; get other side's window size
- dec ah
- sub al,20h ; apply unchar()
- call dewind ; negotiate window size back into al
- spar9: mov trans.windo,al ; store it
- ; decode window info
- push cx ; save a reg
- xor ch,ch
- mov cl,trans.spsiz ; normal packet size
- mov trans.slongp,cx ; assume not using long packets
- pop cx ; restore reg
- cmp ah,2 ; more data (long packet needs two)?
- jae spar9d ; ae = more to look at
- mov ax,trans.slongp ; put above size in ax for final checks
- jmp spar9a ; do final checks (they want longer than us)
- spar9d: test trans.capas,2 ; do they have long packet capability?
- jz sparx ; z = no, skip following lp length fields
- lodsb ; long pkt length, high order byte
- sub al,20h ; apply unchar()
- xor ah,ah
- mul ninefive ; times 95 to dx(hi),ax(lo)
- mov trans.slongp,ax ; store that much
- lodsb ; long pkt length, low order byte
- sub al,20h ; apply unchar()
- xor ah,ah
- add ax,trans.slongp ; plus high order part
- mov trans.slongp,ax ; store it
- or ax,ax ; if result is zero then use regular packets
- jnz spar9a ; non-zero, use what they want
- mov ah,0
- mov al,trans.spsiz ; default to regular packet size
- mov trans.slongp,ax ; and ignore the CAPAS bit (no def 500 bytes)
- spar9a: cmp ax,trans.slong ; longer than we want to do?
- jbe spar9b ; be = no
- mov ax,trans.slong ; limit to our longest sending size
- mov trans.slongp,ax ; and use it
- spar9b: cmp ax,94 ; shorter than normal packet too?
- ja spar9c ; a = no
- mov trans.spsiz,al ; update normal packet size, again
- spar9c: mov ax,temp4 ; recover number of pieces of data
- sparx: pop si
- ret
- SPAR ENDP
-
- ; Set 8-bit quote character based on my capabilities and the other
- ; Kermit's request
-
- DOQUO PROC NEAR
- cmp dtrans.ebquot,'N' ; Can I do 8-bit quoting at all?
- je dq3 ; No - so forget it
- cmp dtrans.ebquot,'Y' ; Can I do it if requested?
- jne dq0 ; No - it's a must that I do it
- mov trans.ebquot,al ; Do whatever he wants
- jmp dq1
- dq0: cmp al,'Y' ; I need quoting - can he do it?
- je dq1 ; Yes - then all is settled
- cmp al,'N' ; No - then don't quote
- je dq3
- cmp al,trans.ebquot ; Both need quoting - chars must match
- jne dq3
- dq1: mov al,trans.ebquot
- cmp al,'Y' ; If Y or N, don't validate prefix
- je dq2
- cmp al,'N'
- je dq2
- call prechk ; Is it in range 33-62, 96-126?
- jnc dq4 ; nc = in range
- mov al,'Y' ; don't do quoting
- dq4: cmp al,trans.rquote ; Same prefix?
- je dq3 ; Not allowed, so don't do quoting.
- cmp al,trans.squote ; Same prefix here?
- je dq3 ; This is illegal too
- mov trans.ebquot,al ; Remember what we decided on
- dq2: ret
- dq3: mov trans.ebquot,'N' ; Quoting will not be done
- ret
- DOQUO ENDP
-
- ; Check if prefix in AL is in the proper range: 33-62, 96-126.
- ; Return carry clear if in range, else return carry set.
- prechk: cmp al,33
- jb prechk2 ; b = out of range
- cmp al,62
- jbe prechk1 ; be = in range 33-62
- cmp al,96
- jb prechk2 ; b = out of range
- cmp al,126
- ja prechk2 ; a = out of range 96-126
- prechk1:clc ; carry clear for in range
- ret
- prechk2:stc ; carry set for out of range
- ret
-
- ; Set checksum length.
- dochk: cmp al,'1' ; Must be '1', '2', or '3'
- jb doc1 ; b = not '1' to '3'
- cmp al,'3'
- jbe doc2 ; be = ok
- doc1: mov al,'1' ; else use default of '1'
- doc2: sub al,'0' ; remove ascii bias
- mov trans.chklen,al ; other side's request is do-able here
- cmp al,trans.chklen ; Do we want the same thing?
- je dochk0 ; e = yes, then we're done
- mov trans.chklen,1 ; No, use single character checksum
- dochk0: ret
-
- ; Set repeat count quote character. The one used must be different than
- ; the control and eight-bit quote characters. Also, both sides must
- ; use the same character
- dorpt: call prechk ; Is it in the valid range?
- jnc dorpt1 ; nc = in range
- mov al,0 ; don't use their value
- dorpt1: cmp al,trans.squote ; Same as the control quote char?
- je dorpt2 ; Yes, that's illegal, no repeats
- cmp al,trans.rquote ; How about this one?
- je dorpt2 ; No good
- cmp al,trans.ebquot ; Same as eight bit quote char?
- je dorpt2 ; Yes, that's illegal too, no repeats
- cmp al,ch ; Are we planning to use same char?
- jne dorpt2 ; No, that's no good either
- mov rptq,ch ; Use repeat quote char now
- dorpt2: ret
-
- ; negotiate window size in al
- dewind: xor al,al ; no windowing at our end
- ret
-
-
- ; Send command
- ; MAIL filspec user@node command
-
- SEND PROC NEAR
- mov mailflg,0 ; send, not mail
- mov temp,0
- jmp short sendm0
- MAIL: mov mailflg,1 ; set flag for mail command vs send
- mov temp,1 ; temp copy of mailflag
- sendm0: mov difsiz,0 ; Assume we'll use original filename
- mov byte ptr sendas,0 ; clear sendas name (in case none)
- mov dx,offset diskio.string ; address of filename string
- ; mov bx,offset filmsg ; Text of help message
- mcmsgb filmsg, cfilmsg
-
- cmp mailflg,0 ; Mail command?
- je sendm1 ; e = no
- mov mailflg,0 ; clear in case error exit
- ; mov bx,offset mailhlp ; Text of help message
- mcmsgb mailhlp, cmailhlp
-
- sendm1: mov ah,cmfile ; get an input file spec
- call comnd
- ret ; Give up on bad parse
- nop
- nop
- cmp flags.cxzflg,0 ; ^X, ^Z, ^C typed?
- je send0 ; e = no, continue
- or errlev,1 ; say send failed
- or fsta.xstatus,1+80h ; set status, failed + intervention
- mov kstatus,1+80h ; global status
- jmp rskp ; yes, quit
- send0: cmp ah,0 ; any text given?
- je send0d ; e = no, prompt
- cmp temp,0 ; Mail command?
- je send00
- jmp send0c ; ne = yes, require address
- send00:
- mov bx,offset sendas ; See if want to send file under dif name
- ; mov dx,offset filhlp ; In case user needs help
- mcmsg filhlp, cfilhlp
-
- mov ah,cmtxt ; allow embedded white space
- call comnd
- ret
- nop
- nop
- jmp sendm3a ; join common completion code
-
- send0d:
- ; mov dx,offset lclfnm ; prompt for local filename
- mcmsg lclfnm, clclfnm
-
- call prompt
- mov dx,offset diskio.string ; reload destination of user's text
- ; mov bx,offset filhlp ; help file
- mcmsgb filhlp, cfilhlp
-
- mov ah,cmfile ; allow paths
- call comnd ; try again for a local filename
- ret
- nop
- nop
- mov temp4,ax
- mov ah,cmcfm
- call comnd
- ret
- nop
- nop
- mov ax,temp4
- cmp flags.cxzflg,0 ; ^X, ^Z, ^C typed?
- je send0a ; e = no, continue
- or errlev,1 ; say send failed
- or fsta.xstatus,1+80h ; set status, failed + intervention
- mov kstatus,1+80h ; global status
- mov mailflg,0
- jmp rskp ; yes, quit
- send0a: cmp ah,0 ; user's byte count
- je send0d ; e = nothing was typed, get some
-
- send0b:
- ; mov dx,offset remfnm ; ask for remote name first
- mcmsg remfnm, cremfnm
-
- cmp temp,0 ; Mail command?
- je sendm2 ; e = no
- ; mov dx,offset mailto ; ask for name@host
- mcmsg mailto, cmailto
-
- sendm2: call prompt
-
- send0c: mov bx,offset sendas ; See if want to send file under dif name
- ; mov dx,offset filhlp ; In case user needs help
- mcmsg filhlp, cfilhlp
-
- cmp temp,0 ; Mail command?
- je sendm3 ; e = no
- ; mov dx,offset mailtohlp ; In case user needs help
- mcmsg mailtohlp, cmailtohlp
-
- sendm3: mov ah,cmtxt ; allow embedded white space
- call comnd
- ret
- nop
- nop
- cmp ah,0 ; text entered?
- je send0b ; e = no, get some
- sendm3a:cmp flags.cxzflg,0 ; ^X, ^Z, ^C typed?
- je send1 ; e = no, continue
- or errlev,1 ; say send failed
- or fsta.xstatus,1+80h ; set status, failed + intervention
- mov kstatus,1+80h ; global status
- mov mailflg,0
- jmp rskp ; yes, quit
- send1: mov al,ah ; store count of user's chars
- mov ah,0
- mov difsiz,ax ; Remember length of new name
- mov ax,temp ; get temp mailflag
- mov mailflg,al ; store in secure area for later
- mov ah,trans.sdelay ; seconds to delay before sending
- shl ah,1 ; times 4*256 to get millisec
- shl ah,1 ; for pcwait
- mov al,1 ; set low byte to 1 for no delay case
- call pcwait ; wait number of millisec in ax
- mov flags.xflg,0 ; Reset flag for normal file send[mtd]
- mov flags.cxzflg,0 ; clear interrupt flag too
- mov bx,offset diskio.string
- cmp byte ptr [bx],'#' ; Is first char a replacement for '?'?
- jne send1f ; ne = no
- mov byte ptr [bx],'?' ; yes. Change '#' for '?'
- send1f: mov bx,offset sendas
- cmp byte ptr [bx],'#' ; Is first char a replacement for '?'?
- jne snd11a
- mov byte ptr [bx],'?' ; yes. Change '#' for '?'
- jmp short snd11a
- ; SEND11 is an entry point for REMote cmds
- SEND11: mov flags.nmoflg,0 ; Reset flags from fn parsing
- mov difsiz,0 ; clear any old 'sendas' filespec
- snd11a: mov kstatus,0 ; global status, success
- mov ah,setdma ; set dta address
- mov dx,offset diskio.dta
- int dos
- mov ah,first2 ; search for first
- mov cx,0 ; consider only regular files
- mov dx,offset diskio.string ; full filename, inc paths
- int dos
- pushf ; save flags
- push dx
- mov ah,setdma ; restore dta to offset buff
- mov dx,offset buff
- int dos
- pop dx
- popf ; restore flags
- jnc send16 ; carry reset = file found
- cmp pack.state,'R' ; was this from a remote GET?
- jne sen11a ; no, print error and continue
- ; mov bx,offset remmsg1 ; else get error message
- mcmsgb remmsg1, cremmsg1
- mov ah,trans.chklen
- mov curchk,ah ; Store checksum length we want to use
- mov trans.chklen,1 ; Send init checksum is always 1 char
- call errpack ; go complain
- mov ah,curchk
- mov trans.chklen,ah ; Checksum length we want to use
- jmp abort ; and abort this
- sen11a: mov ah,prstr
- mov dx,offset crlf
- int dos
- mov ah,prstr
- ; mov dx,offset erms15 ; '?Unable to find file'
- mcmsg erms15, cerms15
-
- int dos
- or errlev,1 ; set DOS error level
- or fsta.xstatus,1 ; set status
- mov kstatus,1 ; global status
- mov ax,1 ; tell statistics this was a send operation
- call endtim ; stop statistics counter
- mov mailflg,0 ; clear Mail flag
- jmp rskp ; pretend successful completion
-
- send16: call serini ; Initialize serial port
- jnc send17 ; nc = success
- or errlev,1 ; say send failed
- or fsta.xstatus,1 ; set status
- mov kstatus,1 ; global status
- test flags.remflg,dquiet ; quiet display mode?
- jnz send16a ; nz = yes. Don't write to screen
- ; mov dx,offset erms14
- mcmsg erms14, cerms14
-
- mov ah,prstr
- int dos ; Print an error message
- send16a:ret ; return failure
-
- send17: call begtim ; get tod for start of transfer
- mov pack.pktnum,0 ; Set the packet number to zero
- mov pack.numtry,0 ; Set the number of tries to zero
- mov pack.numpkt,0 ; Set the number of packets to zero
- mov pack.numrtr,0 ; Set the number of retries to zero
- mov pack.state,'S' ; Set the state to receive initiate
- call ihosts ; initialize the host (clear NAKs)
- call init ; Clear the line and initialize the buffers
- test flags.remflg,dquiet+dserial ; quiet or serial display mode?
- jnz send2 ; nz = yes, suppress 0 retry msg
- call stpos ; Print status of file transfer
- mov ah,prstr ; Be informative
- ; mov dx,offset infms2
- mcmsg infms2, cinfms2
-
- int dos
- send18: test flags.remflg,dquiet+dserial ; quiet or serial display mode?
- jnz send2 ; nz = yes, suppress 0 retry msg
- call rtpos ; Position cursor
- mov ax,0 ; set retry counts to zero
- call nout ; Write the number of retries
-
- send2: call nppos ; Number of packets sent
- mov ax,pack.numpkt
- call nout ; Write the packet number
- cmp pack.state,'D' ; Are we in the data send state?
- jne send3 ; ne = no
- call sdata ; send data
- jmp send2
- send3: cmp pack.state,'F' ; Are we in the file send state?
- jne send3a ; ne = no
- call sfile ; Call send file
- jmp send2
- send3a: cmp pack.state,'a' ; are we in send attributes state?
- jne send3b ; ne = no
- call sattr ; call send attributes
- jmp send2
- send3b: cmp pack.state,'d' ; are we in initialize send data state
- jne send4 ; ne = no
- call sdatini ; do setup for file reading
- jmp send2
-
- send4: cmp pack.state,'Z' ; Are we in the EOF state?
- jne send5
- call seof
- jmp send2
- send5: cmp pack.state,'S' ; Are we in the send initiate state?
- jne send6
- call sinit
- jmp send2
- send6: cmp pack.state,'B' ; Are we in the eot state?
- jne send7
- call seot
- jmp send2
- ; Completion processor section
- send7: push ax
- ;;;; call serrst ; Reset serial port
- pop ax
- mov mailflg,0 ; clear Mail flag
- ; mov dx,offset infms3 ; Completed message
- mcmsg infms3, cinfms3
-
- cmp pack.state,'C' ; Are we in the send complete state?
- je send8 ; e = yes, else failure
- ; mov dx,offset infms4 ; Failed message
- mcmsg infms4, cinfms4
-
- or errlev,1 ; say send failed
- or fsta.xstatus,1 ; set status
- mov kstatus,1 ; global status
-
- send8: cmp flags.cxzflg,0 ; completed normally?
- je send8b ; e = yes, don't bother with this
- or errlev,1 ; say send failed
- or fsta.xstatus,1+80h ; set status, failed + intervention
- mov kstatus,1+80h ; global status
- send8b: mov ax,1 ; tell statistics this was a send operation
- call endtim ; stop statistics counter
- test flags.remflg,dquiet ; quiet display mode?
- jnz send8f ; nz = yes, no printing
- test flags.remflg,dserial ; serial display mode?
- jnz send8c ; nz = yes, skip positioning
- push dx
- call stpos
- pop dx
- send8c: mov ah,prstr
- cmp flags.cxzflg,0 ; Completed or interrupted?
- je send8d ; e = no interruption
- ; mov dx,offset infms6 ; Say transfer was interrupted
- mcmsg infms6, cinfms6
-
- send8d: int dos
- cmp flags.belflg,0 ; Bell desired?
- je send8e ; e = no
- mov dx,offset ender ; Ring them bells
- int dos
- send8e: test flags.remflg,dserial ; serial display mode?
- jnz send8f ; nz = yes, no cursor positioning
- call clrmod
- call rprpos
- send8f: jmp rskp
- SEND ENDP
-
- ; Send routines
-
- ; Send initiate
- SINIT PROC NEAR
- mov dl,imxtry
- cmp pack.numtry,dl ; Have we reached the maximum number of tries?
- jl sinit2 ; l = no
- test flags.remflg,dquiet ; quiet display mode?
- jnz sinit1 ; nz = yes. Don't write to screen
- call erpos
- ; mov dx,offset erms14
- mcmsg erms14, cerms14
-
- mov ah,prstr
- int dos ; Print an error message
- sinit1: mov ah,trans.chklen
- mov curchk,ah ; Store checksum length we want to use
- mov trans.chklen,1 ; Send init checksum is always 1 char
- ; mov bx,offset erms20
- mcmsgb erms20, cerms20
-
- call errpack ; Send error packet just in case
- mov ah,curchk
- mov trans.chklen,ah ; Checksum length we want to use
- jmp abort ; Change the state to abort
- sinit2: inc pack.numtry ; Save the updated number of tries
- mov bx,offset data ; Get a pointer to our data block
- mov ah,dtrans.seol ; restore default end-of-line char
- mov trans.seol,ah
- mov ah,dtrans.ebquot ; our default 8-bit quoting
- mov trans.ebquot,ah ; active 8-bit quoting
- call rpar ; Set up the parameter information
- xchg ah,al
- mov ah,0
- mov pack.datlen,ax ; Save the number of arguments
- mov ax,pack.numpkt ; Get the packet number
- mov pack.seqnum,ax
- mov ah,trans.chklen
- mov curchk,ah ; Store checksum length we want to use
- mov trans.chklen,1 ; Send init checksum is always 1 char
- call pktsize ; report packet size
- mov ah,'S' ; Send initiate packet
- call sndpak ; send the packet
- call rpack ; Get a packet
- jmp sini23 ; Trashed packet don't change state, retry
- nop
- push ax
- mov ah,curchk
- mov trans.chklen,ah ; Checksum length we want to use
- pop ax
- call acknak ; was it ok?
- cmp al,0 ; maybe an ack?
- je sini22 ; yes, go handle it
- cmp al,1 ; maybe a nak?
- jne sinit4 ; no, check for error or something
- ret ; else just return and try again
- sini22: mov ax,pack.datlen
- mov bx,offset data ; point to data for spar
- call spar ; Read in the data
- call packlen ; Get max send packet size
- mov pack.numtry,0 ; Reset the number of tries
- cmp mailflg,0 ; non-zero to do Mail command
- je sini24 ; e = send, not mail command
- cmp flags.attflg,0 ; allowed to do file attributes?
- je sinit6 ; e = no, so no Mail
- test trans.capas,8 ; can they do file attributes?
- jz sinit6 ; z = no, so cannot do Mail
- sini24: mov pack.state,'F' ; Set the state to file send
- call getfil ; Open the file
- jmp abort ; Something is wrong, die
- mov filopn,1 ; Disk file is open
- ret
- sini23: mov ah,curchk ; Restore desired checksum length
- mov trans.chklen,ah
- jmp updrtr ; Update retry counter and return
-
- sinit4: cmp ah,'M' ; Message packet?
- jne sinit4e ; ne = no
- call dodec ; decode it
- jmp error1 ; display it and return
-
- sinit4e:cmp ah,'E' ; Is it an error packet
- jne sinit5
- call error
- sinit5: jmp abort
- ; say Mail not supported by host
- sinit6: test flags.remflg,dquiet ; quiet display mode?
- jnz sinit7 ; nz = yes. Don't write to screen
- call erpos
- ; mov dx,offset erms25
- mcmsg erms25, cerms25
-
- mov ah,prstr
- int dos ; Print an error message
- sinit7: mov pack.state,'B' ; go to EOT state
- ret
- SINIT ENDP
-
- ; Send file header
-
- SFILE PROC NEAR
- mov dl,maxtry
- cmp pack.numtry,dl ; Have we reached the maximum number of tries?
- jl sfile1 ; l = no
- test flags.remflg,dquiet ; quiet display mode?
- jnz sfile0 ; nz = yes. Don't write to screen
- call erpos
- ; mov dx,offset erms14
- mcmsg erms14, cerms14
-
- mov ah,prstr
- int dos ; Print an error message
- sfile0:
- ; mov bx,offset erms21
- mcmsgb erms21, cerms21
-
- call errpack ; Send error packet just in case
- jmp abort ; Change the state to abort
- sfile1: inc pack.numtry ; Increment it
- mov flags.cxzflg,0 ; Clear ^X,^Z flag.
- mov si,offset diskio.fname ;addr of asciiz filename without paths
- mov di,offset data ; destination
- call strcpy ; copy filename there
- push dx
- mov dx,offset data
- call strlen ; get length (w/o terminator) into cx
- pop dx
- mov ch,0
- test flags.remflg,dquiet ; quiet display mode?
- jnz sfil13 ; nz = yes, no printing
- call prtfn ; print filename in data
- sfil13: call newfn ; show possible new filename, put length in cx
- call doenc ; Do encoding; length is in cx
- mov ax,pack.pktnum ; Get the packet number
- mov pack.seqnum,ax
- mov ah,'F' ; File header packet
- cmp flags.xflg,0 ; remote display requested?
- je sfl13y ; e = no
- mov ah,'X' ; use X rather than F packet for remote
- sfl13y: call pktsize ; report packet size
- call sndpak ; send the packet
- call rcvpak ; Get a packet
- call acknak ; see what they had to say
- cmp al,0 ; ack'd ok?
- je sfil14 ; yes, on to next state
- cmp al,1 ; maybe a nak?
- jne sfile3 ; no, check for error
- ret ; if nak, just return and try again
- sfil14: call fackmsg ; get/show any embedded message
- mov pack.state,'a' ; set file attributes as next state
- ret
-
- sfile3: cmp ah,'M' ; Message packet?
- jne sfile4 ; ne = no
- call dodec ; decode it
- jmp error1 ; display it and return
-
- sfile4: cmp ah,'E' ; Is it an error packet
- jne sfile4 ; ne = no
- call dodec ; Do all decoding
- call error
- sfile5: jmp abort
- SFILE ENDP
-
- ; Send file attributes. Attributes: file size in bytes and kilobytes,
- ; file time and date, machine identification. [jrd]
-
- SATTR PROC NEAR
- cmp flags.attflg,0 ; allowed to do file attributes?
- je satt0 ; e = no
- test trans.capas,8 ; can we do file attributes?
- jnz satt1 ; nz = yes
- satt0: mov pack.state,'d' ; set the state to initiate send-data
- ret
- satt1: push es ; save es around this work
- push ds
- pop es ; set es to datas segment for es:di
- cld
- mov data,'1' ; File length (Bytes) specifier
- mov dx,diskio.sizehi ; high word of length
- mov ax,diskio.sizelo ; low word of length
- mov di,offset data+2 ; where to store data (for lnout)
- call lnout ; convert file length, write to [di++]
- mov cx,di ; compute field length
- sub cx,offset data+2
- add cl,32 ; field length to ascii
- mov data+1,cl ; length. Done with File Size
- ; Kilobyte attribute
- mov byte ptr[di],'!' ; File length (Kilobytes) specifier
- inc di
- mov temp4,di ; remember place for count field
- inc di ; data field
- mov dx,diskio.sizehi ; high word of length, from file open
- mov ax,diskio.sizelo ; low word of length
- add ax,1023 ; add 1023 to round up
- adc dx,0
- mov al,ah ; do divide by 1024 bytes
- mov ah,dl
- mov dl,dh ; divide by 256 part
- mov dh,0
- ror dl,1 ; low bit to carry flag
- rcr ax,1 ; divide by two, with carry in
- clc
- ror dl,1 ; low bit to carry flag
- rcr ax,1 ; divide by two, with carry in
- and dl,3fh ; keep low six bits
- call lnout ; convert file length
- mov cx,di ; compute field length
- sub cx,temp4 ; count field location
- add cl,32-1 ; field length to ascii
- push di
- mov di,temp4 ; point at count field
- mov byte ptr[di],cl ; store field length
- pop di ; Done with Kilobyte attribute
- ; File date and time:
- mov al,'#' ; creation date/time specifier
- stosb ; and point at field length
- mov al,17+32 ; length of date/time field, to ascii
- stosb
- mov ah,0
- mov al,diskio.dta+25 ; yyyyyyym from DOS via file open
- shr al,1 ; get year
- add ax,1980 ; add bias
- mov dx,0
- call lnout ; put year (1988) in buffer
- mov ax,word ptr diskio.dta+24 ; yyyyyyyym mmmddddd year+month+day
- shr ax,1 ; month to al
- mov ah,0
- mov cl,4
- shr al,cl ; month to low nibble
- mov byte ptr[di],'0' ; leading digit
- inc di
- cmp al,9 ; more than one digit?
- jbe satt2 ; be = no
- mov byte ptr[di-1],'1' ; new leading digit
- sub al,10 ; get remainder
- satt2: add al,'0' ; to ascii
- stosb ; end of month
- mov al,diskio.dta+24 ; get day of month
- and al,1fh ; select day bits
- mov ah,0
- mov cl,10
- div cl ; quot = al, rem = ah
- add ax,'00' ; add ascii bias
- stosw ; leading digit and end of date
- mov al,' ' ; space separator
- stosb
- mov al,diskio.dta+23 ; hours hhhhhmmm
- mov cl,3
- shr al,cl ; move to low nibble
- mov ah,0
- mov cl,10
- div cl ; quot = al, rem = ah
- add ax,'00' ; add ascii bias
- stosw ; store hours
- mov al,':' ; separator
- stosb
- mov ax,word ptr diskio.dta+22 ; get minutes: hhhhhmmm mmmsssss
- mov cl,5
- shr ax,cl ; minutes to low byte
- and al,3fh ; six bits for minutes
- mov ah,0
- mov cl,10
- div cl
- add ax,'00' ; add ascii bias
- stosw
- mov al,':' ; separator
- stosb
- mov al,byte ptr diskio.dta+22 ; get seconds (double secs really)
- and al,1fh
- shl al,1 ; DOS counts by two sec increments
- mov ah,0
- mov cl,10
- div cl
- add ax,'00' ; add ascii bias
- stosw
- mov ax,'".' ; machine indicator(.), 2 data bytes
- stosw
- mov ax,'8U' ; U8 = Portable O/S, MSDOS
- stosw
- pop es ; recover es register
- cmp mailflg,0 ; Mailing?
- je satt3 ; e = no
- mov byte ptr [di],'+' ; Mail specification
- inc di
- mov si,offset sendas ; user@host field
- mov dx,si
- call strlen ; get length into cl
- push cx ; save address length
- inc cl ; include M for disposition = mail
- add cl,' ' ; add ascii bias
- mov [di],cl ; store in length field
- inc di
- mov byte ptr [di],'M' ; mail the file
- inc di
- pop cx ; recover address length
- jcxz satt3 ; z = empty field
- push es
- push ds
- pop es ; use es:di pointing to datas segment
- cld
- rep movsb ; append address text to field
- pop es
- satt3: sub di,offset data ; get length of data
- mov pack.datlen,di ; data length for packet
- call pktsize ; report packet size
- mov ax,pack.pktnum ; get the packet number
- mov pack.seqnum,ax
- mov ah,'A' ; Attributes packet
- call sndpak ; send the packet
- call rcvpak ; get response
- call acknak ; see what they had to say
- cmp al,0 ; ack'd ok?
- je satt5 ; e = yes, on to next state
- cmp al,1 ; maybe a nak?
- jne satt6 ; ne = no, check for error
- ret ; if nak, just return and try again
- satt5: cmp pack.datlen,0 ; any data in the ACK?
- je satt5d ; e = no
- cmp data,'N' ; are they refusing this file?
- jne satt5d ; ne = no
- test flags.remflg,dquiet ; quiet display mode?
- jnz satt5a ; nz = yes. Don't write to screen
- call erpos ; Position the cursor
- mov ah,prstr
- ; mov dx,offset erms26 ; say host rejected the file
- mcmsg erms26, cerms26
-
- int dos
- satt5a: mov pack.state,'Z' ; send EOF with Discard
- mov flags.cxzflg,'X' ; simulate Control-X to discard
- or errlev,1 ; say send failed
- or fsta.xstatus,1+80h ; set status, failed + intervention
- mov kstatus,1+80h ; global status
- ret
- satt5d: mov pack.state,'d' ; next state is initiate send-data
- ret
- satt6: cmp ah,'E' ; Is it an error packet
- jne satt7 ; ne = no
- call dodec ; Do all decoding
- call error
- satt7: jmp abort
- SATTR ENDP
-
- ; Send data
- ;
- ; set up initial data buffer from file, 'd' state
- sdatini proc near
- mov flags.filflg,0FFH ; Indicate file buffer is empty
- mov pack.state,'D'
- jmp sdat23 ; read first buffer from file
- sdatini endp
-
- ; Send main body of file, 'D' state
-
- SDATA PROC NEAR
- cmp flags.cxzflg,0 ; Have we seen ^X or ^Z?
- je sdata2 ; Nope, just continue
- cmp flags.cxzflg,'C' ; Stop it all?
- jne sdata1 ; It was a ^X or ^Z
- mov pack.state,'A' ; It was a ^C -- abort
- ret
- sdata1: mov pack.state,'Z' ; Else, abort sending the file
- ret
- sdata2: mov dl,maxtry
- cmp pack.numtry,dl ; Have we reached the maximum number of tries?
- jl sdata3 ; l = no
- test flags.remflg,dquiet ; quiet display mode?
- jnz sdat2a ; nz = yes. Don't write to screen
- call erpos
- ; mov dx,offset erms14
- mcmsg erms14, cerms14
-
- mov ah,prstr
- int dos ; Print an error message
- sdat2a:
- ; mov bx,offset erms22
- mcmsgb erms22, cerms22
-
- call errpack ; Send error packet just in case
- jmp abort ; Change the state to abort
- sdata3: inc pack.numtry ; Increment it
- mov cx,siz ; number to transfer
- mov pack.datlen,cx ; length of data in packet
- call movpak ; from filbuf to buffer data
- mov ax,pack.pktnum ; Get the packet number
- mov pack.seqnum,ax ; store in packet
- call pktsize ; report packet size
- mov ah,'D' ; Data packet
- call sndpak ; send the packet
- call rcvpak ; Get a packet
- call acknak ; see if ack or nak, check packet number
- cmp al,0 ; 0 => ack ok, go on
- je sdat11 ; ack, check for data in response
- cmp al,1 ; 1 => nak, retry count incremented, try again
- jne sdat15 ; else look for other packet types
- ret ; else return
-
- sdat11: cmp pack.datlen,0 ; any data in ACK response?
- je sdat23 ; e = no
- call dackmsg ; get/show any embedded message
- mov bl,data ; get 1st byte
- cmp bl,'X' ; someone typed control X?
- je sdat24 ; e = yes
- cmp bl,'Z' ; Control Z? Corrects earlier proto error
- jne sdat23 ; not X or Z, just keep going
- sdat24: mov flags.cxzflg,bl ; set flag appropriately
- mov pack.state,'Z' ; simulate eof
- ret ; and return
-
- SDAT23: call gtchr ; fill buffer from file
- jmp sdat12 ; Error go see if its EOF
- nop ; make three bytes
- mov siz,ax ; Save the size of the data gotten
- ret
- sdat12: cmp ah,0FFH ; Is it EOF?
- je sdat13 ; e = yes
- jmp abort ; If not give up
- sdat13: mov pack.state,'Z' ; Set the state to EOF
- ret
-
- sdat15: cmp ah,'M' ; Message packet?
- jne sdat16 ; ne = no
- call dodec ; decode it
- jmp error1 ; display it and return
-
- sdat16: cmp ah,'E' ; Is it an error packet
- jne sdat17
- call dodec ; Do all decoding
- call error ; display and change state to Abort
- sdat17: jmp abort
- SDATA ENDP
-
- ; Send EOF
-
- SEOF PROC NEAR
- mov dl,maxtry
- cmp pack.numtry,dl ; Have we reached the maximum number of tries?
- jl seof1 ; l = no
- test flags.remflg,dquiet; quiet display mode?
- jnz seof0 ; nz = yes. Don't write to screen
- call erpos ; Position cursor
- ; mov dx,offset erms14
- mcmsg erms14, cerms14
-
- mov ah,prstr
- int dos ; Print an error message
- seof0:
- ; mov bx,offset erms23
- mcmsgb erms23, cerms23
-
- call errpack ; Send error packet just in case
- jmp abort ; Change the state to abort
- seof1: inc pack.numtry ; Increment it
- mov ax,pack.pktnum ; Get the packet number
- mov pack.seqnum,ax
- mov pack.datlen,0 ; No data
- cmp flags.cxzflg,0 ; Seen a ^X or ^Z?
- je seof11 ; Nope, send normal EOF packet
- mov data,'D' ; Use "D" for discard
- mov pack.datlen,1 ; Set data size to 1
- or errlev,1 ; say send failed
- or fsta.xstatus,1+80h ; set status, failed + intervention
- mov kstatus,1+80h ; global status
- seof11: mov cx,pack.datlen ; Put size in CX
- call doenc ; Encode the packet
- call pktsize ; report packet size
- mov ah,'Z' ; EOF packet
- call sndpak ; send the packet
- call rcvpak ; Get a packet
- call acknak ; see what they had to say
- cmp al,0 ; ack?
- je seof12 ; e = yes, go close file and proceed
- cmp al,1 ; maybe a nak?
- jne seof3 ; no, check for error packet
- ret ; if nak, just return
-
- seof12: call dackmsg ; get/show any embedded message
- mov ah,close2 ; DOS 2.0 close file
- push bx
- mov bx,diskio.handle ; file handle
- int dos
- pop bx
- call GTNFIL ; Get the next file
- jmp seof13 ; No more
- nop ; make three bytes
- mov pack.state,'F' ; Set the state to file send
- cmp flags.cxzflg,'X' ; Control-X seen?
- jne seof14
- call cxmsg ; Clear out the interrupt msg
- or errlev,1 ; say send failed
- or fsta.xstatus,1+80h ; set status, failed + intervention
- mov kstatus,1+80h ; global status
- seof14: mov flags.cxzflg,0 ; Reset the flag
- ret
- seof13: mov pack.state,'B' ; Set the state to EOT
- mov filopn,0 ; No files open
- mov difsiz,0 ; clear original filename
- mov byte ptr sendas,0 ; clear sendas name
- ret
- seof3: cmp ah,'E' ; Is it an error packet?
- jne seof4
- call dodec ; Decode packet
- call error
- seof4: jmp abort
- SEOF ENDP
-
-
- ; Send EOT
-
- SEOT PROC NEAR
- mov dl,maxtry
- cmp pack.numtry,dl ; Have we reached the maximum number of tries?
- jl seot1 ; l = no
- test flags.remflg,dquiet ; quiet display mode?
- jnz seot0 ; nz = yes. Don't write to screen
- call erpos ; Position cursor
- ; mov dx,offset erms14
- mcmsg erms14, cerms14
-
- mov ah,prstr
- int dos ; Print an error message
- seot0:
- ; mov bx,offset erms24
- mcmsgb erms24, cerms24
-
- call errpack ; Send error packet just in case
- jmp abort ; Change the state to abort
- seot1: inc pack.numtry ; Increment it
- mov ax,pack.pktnum ; Get the packet number
- mov pack.seqnum,ax
- mov pack.datlen,0 ; No data
- call pktsize ; report packet size
- mov ah,'B' ; End of Session packet
- call sndpak ; send the packet
- call rcvpak ; Get a packet
- call acknak ; see if good ack or nak
- cmp al,0 ; ack'd ok?
- je seot12 ; e = yes, done with this
- cmp al,1 ; maybe a nak?
- jne seot3 ; ne = no, check for error
- ret ; else just return
- seot12: call fackmsg ; get/show any embedded message
- mov pack.state,'C' ; Set state to file completed
- ret
-
- seot3: cmp ah,'E' ; Is it an error packet
- jne seot4
- call dodec ; Do all decoding
- call error
- seot4: jmp abort
- SEOT ENDP
-
- sndpak proc near ; send packet with retries
- call spack
- jmp updrtr
- nop
- ret
- sndpak endp
-
- rcvpak proc near ; receive packet with retries
- call rpack ; Get a packet
- jmp updrtr ; Trashed packet, retry
- nop
- ret
- rcvpak endp
-
- ; check the current packet for an ack or nak and handle it from any of
- ; the send states. Returns: 0 if an ack received with the correct expected
- ; packet number, or if a nak received with the NEXT packet number (the
- ; packet number is incremented, retry count reset); 1 if a nak or ack
- ; with a bad packet number is received, retry count is updated and displayed.
- ; A Timeout packet (type 'T') simply invokes a retry and a returned 1.
- ; Finally, 2 is returned if anything else is seen
- ;
-
- ACKNAK PROC NEAR
- cmp ah,'Y' ; ack packet?
- jne ackna1 ; ne = no, keep going
- mov bx,pack.pktnum
- cmp bx,pack.seqnum ; is it what we were expecting?
- jne ackna2 ; no, update retries and punt
- ; packet ok, increment packet number
- ackna0: mov bx,pack.pktnum ; reload packet number (!!!)
- inc bx
- and bx,03fh ; increment packet number
- mov pack.pktnum,bx ; store back
- inc pack.numpkt ; increment # of packets
- mov pack.numtry,0
- mov al,0 ; ack'd ok
- ret
- ; not a 'Y'..
- ackna1: cmp ah,'N' ; a nak?
- je ackna5 ; yes, go on
- cmp ah,'T' ; Timeout?
- je ackna3 ; e = yes, not a NAK but do a retry
- mov al,2
- ret ; unknown packet type
- ackna5: mov bx,pack.pktnum
- inc bx
- and bx,3fh
- inc fsta.nakrcnt ; count received NAK for statistics
- cmp bx,pack.seqnum ; maybe a nak for pktnum+1?
- je ackna0 ; yes, treat as ack
- jne ackna3
- ; nak or bad ack, update retry stuff
- ackna2: inc fsta.nakrcnt ; count received NAK for statistics
- ackna3: push ax
- call rtpos ; Position cursor
- inc pack.numrtr ; Increment the number of retries
- mov ax,pack.numrtr
- call nout ; Write the number of retries
- pop ax
- mov al,1 ; nak code
- ret ; and return
- ACKNAK ENDP
-
- ; Display message in ACK's to D packets. Requires a leading protocol char
- ; and expects message to be encoded.
- dackmsg proc near
- cmp pack.datlen,1 ; any embedded message?
- jbe dackmsgx ; be = no (skip single char msgs)
- test flags.remflg,dquiet ; quiet display mode?
- jnz dackmsgx ; nz = yes, don't write to screen
- push ax
- push dx
- call cxmsg ; clear message space in warning area
- call dodec ; decode message, including X/Z/other
- mov dx,offset data+1 ; point to asciiz message
- call prtasz ; display it
- pop dx
- pop ax
- dackmsgx:ret
- dackmsg endp
-
- ; Display messages in ACKs to F packets. Expects message to be not encoded.
- fackmsg proc near ; look for in ack
- cmp pack.datlen,0 ; any embedded message?
- je fackmsgx ; e = no
- test flags.remflg,dquiet ; quiet display mode?
- jnz fackmsgx ; nz = yes, don't write to screen
- push ax
- push dx
- call cxmsg ; clear message space in warning area
- call dodec;;;decode
- mov dx,offset data ; point to asciiz message
- call prtasz ; display it
- pop dx
- pop ax
- fackmsgx:ret
- fackmsg endp
-
- ; newfn -- move replacement name from buffer sendas to buffer data
- ; update cx to new filename length
- newfn: cmp difsiz,0 ; Sending file under different name?
- je newf4 ; e = no, so don't give new name
- mov si,offset sendas ; source field
- mov di,offset fsta.xname ; statistics name area
- call strcpy
- test flags.remflg,dquiet ; quiet display mode?
- jnz newfa ; nz = yes. Don't write to screen
- mov ah,prstr
- ; mov dx,offset asmsg ; display ' as '
- mcmsg asmsg, casmsg
-
- cmp mailflg,0 ; mail?
- je newfn1 ; e = no
- mov dx,offset mailto ; display ' To: '
- newfn1: int dos
- mov ah,conout ; use printable output
- cmp mailflg,0 ; mail?
- je newfa ; e = no
- mov dx,offset sendas ; get name
- call prtasz ; print asciiz string
- jmp newf4 ; don't replace filename
- newfa: mov si,offset sendas ; Buffer where the name is
- mov di,offset data
- mov cx,difsiz ; Length of name
- inc cx ; plus null terminator
- newf0: lodsb ; Get a character into al
- stosb
- test flags.remflg,dquiet ; quiet display mode (should we print)?
- jnz newf2 ; nz = yes
- mov dl,al ; set into dl for display
- int dos ; Print them
- newf2: loop newf0
- mov cx,difsiz ; Reset the length field
- newf4: test flags.remflg,dserial ; serial display mode?
- jz newf5 ; z = no
- mov dx,offset crlf ; start with cr/lf for serial display
- mov ah,prstr
- int dos
- newf5: ret
-
- ; Do encoding. Expect CX to be the data size
-
- doenc: jcxz doen0
- mov chrcnt,cx ; Number of bytes of source data
- mov bufpnt,offset data ; Source of data
- mov bx,offset nulref ; Null routine for refilling buffer
- mov ah,rptq
- mov origr,ah ; Save repeat prefix here
- mov rptct,1 ; Number of times char is repeated
- mov rptval,0 ; Value of repeated char
- call encode ; Make a packet with size in AX
- nop
- nop
- nop
- mov pack.datlen,ax ; Store length of data field
- mov cx,ax
- call movpak ; Move to data part of packet
- cmp chrcnt,0 ; Did all chars fit into the buffer?
- jne doen1 ; ne = no, we have an error condition
- clc ; clear c bit for success
- doen0: ret
- doen1: stc ; set c bit for did not fit condition
- ret
-
- ; CX is set before this is called
- movpak: push es
- mov ax,ds
- mov es,ax
- cld
- mov si,offset filbuf ; Move from here
- mov di,offset data ; to here
- shr cx,1 ; divide by two (words), set carry
- jnc movpak1 ; nc = even number of bytes
- movsb ; do the single move for odd count
- movpak1:cmp cx,0
- jle movpak2
- rep movsw
- movpak2:pop es
- ret
-
- ; Dodecoding
- dodec:
- push ax ; Save packet size
- mov bx,offset data ; Address of data
- mov ax,offset nulr ; Routine to dump buffer (null)
- mov bufpnt,offset decbuf ; Where to put output
- mov chrcnt,maxpack ; Buffer size
- mov cx,pack.datlen ; Size of data
- jcxz dodc0 ; z = nothing to transfer
- call decode
- nop
- nop
- nop
- dodc0: call decmov ; Move decoded data back to "data" buffer
- pop ax
- ret
-
- ; Move decoded data from decode buffer back to "data".
- decmov: push si
- push di
- push es
- mov ax,ds
- mov es,ax
- cld
- mov cx,bufpnt ; Last char we added
- sub cx,offset decbuf ; Get actual number of characters
- mov pack.datlen,cx ; Remember size of real data
- mov si,offset decbuf ; Data is here
- mov di,offset data ; Move to here
- shr cx,1 ; divide by two (words), set carry
- jnc decmov1 ; nc = even number of bytes
- movsb ; do single move
- decmov1:cmp cx,0
- jle decmov2 ; le = none to do
- rep movsw ; Copy the data
- decmov2:mov al,0 ; Null to end the string
- stosb
- pop es
- pop di
- pop si
- ret
-
- ; Abort
-
- ABORT PROC NEAR
- mov difsiz,0 ; clear original filename
- mov byte ptr sendas,0 ; clear sendas name
- mov mailflg,0 ; clear Mail flag
- cmp filopn,0 ; Any disk files open?
- je abort0 ; No so don't do a close
- mov ah,close2 ; DOS 2.0 close file
- push bx
- mov bx,diskio.handle ; file handle
- int dos
- pop bx
- mov filopn,0 ; say file is closed now
- abort0: mov pack.state,'A' ; Otherwise abort
- or errlev,1 ; set DOS error level
- or fsta.xstatus,1 ; set status
- mov kstatus,1 ; global status
- ret
- ABORT ENDP
-
- ; This is where we go if we get an error packet. A call to ERROR
- ; positions the cursor and prints the message. A call to ERROR1
- ; just prints a CRLF and then the message
-
- ERROR PROC NEAR
- mov pack.state,'A' ; Set the state to abort
- test flags.remflg,dquiet ; quiet display mode?
- jnz errorx ; nz = yes. Don't write to screen
- call erpos ; Position the cursor
- jmp error2
- ERROR1: mov ah,prstr ; entry point for Server Generic cmds
- mov dx,offset crlf
- int dos
- error2: mov dx,offset data ; error message string
- push bx
- mov bx,pack.datlen ; Get the length of the data
- add bx,dx ; Get to the end of the string
-
- mov byte ptr [bx],0 ; terminate string
- pop bx
- call prtasz ; print asciiz string
- pop bx
- errorx: ret
- ERROR ENDP
-
- ; Set the maximum send data packet size; modified for long packets
- PACKLEN PROC NEAR
- push ax
- push cx
- xor ah,ah
- mov al,trans.spsiz ; Maximum send packet size for Regular pkts.
- cmp ax,trans.slongp ; negotiated long packet max size
- jae pack2 ; ae = use regular packets
- mov ax,trans.slongp ; else use long kind
- sub ax,3 ; minus extended count & checksum
- cmp ax,(95*94-1-2) ; longer than Long?
- jle pack2 ; le = no, Long will do
- dec ax ; minus one more for extra long count
- pack2: sub ax,2 ; minus Sequence, Type
- sub al,trans.chklen ; And minus Checksum chars
- sbb ah,0 ; borrow propagate
- cmp trans.ebquot,'N' ; Doing 8-bit Quoting?
- je pack0 ; Nope so we've got our size
- cmp trans.ebquot,'Y'
- je pack0 ; Not doing it in this case either
- dec ax ; Another 1 for 8th-bit Quoting.
- pack0: cmp rptq,0 ; Doing repeat character Quoting?
- je pack1 ; Nope, so that's all for now
- dec ax ; minus repeat prefix
- dec ax ; and repeat count
- pack1: dec ax ; for last char might being a control code
- mov trans.maxdat,ax ; Save max length for data field
- pop cx
- pop ax
- ret
- PACKLEN ENDP
-
- ; Print the number in AX on the screen in decimal rather that hex
-
- NOUT PROC NEAR
- test flags.remflg,dserial ; serial display mode?
- jnz pnout ; nz = use "dot and plus" for serial mode
- test flags.remflg,dquiet ; quiet display mode?
- jnz nout1 ; nz = yes. Don't write to screen
- call decout ; call standard decimal output routine
- nout1: ret
-
-
- pnout: or ax,ax ; display packet in serial display mode
- jz pnoutx ; z = nothing to display
- push ax ; for serial mode display
- push dx ; output .........+.........+ etc
- mov temp,10
- mov dx,0
- div temp ; number/10. (AX=quo, DX=rem)
- push ax ; save around printing
- push dx ; save around initial printing
- cmp dx,0 ; remainder non-zero?
- jne pnout1 ; ne = yes
- mov dl,'+' ; symbol plus for tens
- jmp pnout2 ; display it
- pnout1: mov dl,'.' ; symbol for between tens
- pnout2: mov ah,conout ; output to console
- int dos
- pop dx ; recover remainder
- pop ax ; recover quotient
- or dx,dx ; check for multiples of 70, to break lines
- jnz pnout3 ; nz = non-zero remainder, just exit
- mov temp,7 ; divide ax by 7 (dx is zero by construction)
- div temp ; ax = quotient, dx = remainder
- or dx,dx ; zero remainder?
- jnz pnout3 ; nz = non-zero remainder, just exit
- mov ah,prstr ; output cr/lf after every 70th chars
- mov dx,offset crlf
- int dos
- pnout3: pop dx
- pop ax
- pnoutx: ret
- NOUT ENDP
-
- ; Jumping to this location is like retskp. It assumes the instruction
- ; after the call is a jmp addr
-
- RSKP PROC NEAR
- pop bp
- add bp,3
- push bp
- ret
- RSKP ENDP
- code ends
- end
-